﻿using System;
using System.Collections.Generic;
using System.Linq;

public class CrcHelper {
    /// <summary>
    /// CRC校验
    /// </summary>
    /// <param name="data">校验数据</param>
    /// <returns>高低8位</returns>
    public static IEnumerable<string> GetCrc16 (IEnumerable<string> data) {
        var crcBuf = data.Select (str => byte.Parse (str, System.Globalization.NumberStyles.AllowHexSpecifier)).ToArray ();
        //计算并填写CRC校验码
        var crc = 0xffff;
        var len = crcBuf.Length;
        for (var n = 0; n < len; n++) {
            byte i;
            crc = crc ^ crcBuf[n];
            for (i = 0; i < 8; i++) {
                var tt = crc & 1;
                crc = crc >> 1;
                crc = crc & 0x7fff;
                if (tt == 1) {
                    crc = crc ^ 0xa001;
                }
                crc = crc & 0xffff;
            }
        }

        var res = new [] {
            Convert.ToString ((byte) (crc & 0xff), 16).PadLeft (2, '0'),
            Convert.ToString ((byte) ((crc >> 8) & 0xff), 16).PadLeft (2, '0')
        };
        return res;
    }

    /// <summary>
    /// CRC校验
    /// </summary>
    /// <param name="data">校验数据</param>
    /// <returns>高低8位</returns>
    public static IEnumerable<string> GetCrc16 (IEnumerable<byte> data) {
        var crcBuf = data.ToArray ();
        //计算并填写CRC校验码
        var crc = 0xffff;
        var len = crcBuf.Length;
        for (var n = 0; n < len; n++) {
            byte i;
            crc = crc ^ crcBuf[n];
            for (i = 0; i < 8; i++) {
                var tt = crc & 1;
                crc = crc >> 1;
                crc = crc & 0x7fff;
                if (tt == 1) {
                    crc = crc ^ 0xa001;
                }
                crc = crc & 0xffff;
            }
        }

        var res = new [] {
            Convert.ToString ((byte) (crc & 0xff), 16).PadLeft (2, '0'),
            Convert.ToString ((byte) ((crc >> 8) & 0xff), 16).PadLeft (2, '0')
        };
        return res;
    }

      /// <summary>
    /// CRC校验 
    /// 从高到低位
    /// </summary>
    /// <param name="data">校验数据</param>
    /// <returns>高低8位</returns>
    public static IEnumerable<byte> GetCrc16_HL_Bytes (IEnumerable<byte> data) {
        var crcBuf = data.ToArray ();
        //计算并填写CRC校验码
        var crc = 0xffff;
        var len = crcBuf.Length;
        for (var n = 0; n < len; n++) {
            byte i;
            crc = crc ^ crcBuf[n];
            for (i = 0; i < 8; i++) {
                var tt = crc & 1;
                crc = crc >> 1;
                crc = crc & 0x7fff;
                if (tt == 1) {
                    crc = crc ^ 0xa001;
                }
                crc = crc & 0xffff;
            }
        }

        var res = new [] {
            (byte) (crc & 0xff),
            (byte)  ((crc >> 8) & 0xff) 
        };
        return res;
    }
     /// <summary>
    /// CRC校验 
    /// 从高到低位
    /// </summary>
    /// <param name="data">校验数据</param>
    /// <param name="isHL">是否 "高->低" ,否则 "低->高"</param>
    /// <returns>校验完的数据</returns>
    public static IEnumerable<byte> To_Crc16_Bytes (  IEnumerable<byte> data, bool isHL=true) {
        var crcBuf = data.ToArray ();
        //计算并填写CRC校验码
        var crc = 0xffff;
        var len = crcBuf.Length;
        for (var n = 0; n < len-2; n++) {
            byte i;
            crc = crc ^ crcBuf[n];
            for (i = 0; i < 8; i++) {
                var tt = crc & 1;
                crc = crc >> 1;
                crc = crc & 0x7fff;
                if (tt == 1) {
                    crc = crc ^ 0xa001;
                }
                crc = crc & 0xffff;
            }
        }

        if(isHL){
        crcBuf[len-1]= (byte) (crc & 0xff);
        crcBuf[len-2]= (byte)  ((crc >> 8) & 0xff);
        }else 
        {
         crcBuf[len-2]= (byte) (crc & 0xff);
         crcBuf[len-1]= (byte)  ((crc >> 8) & 0xff);
        }
       
        return crcBuf;
    }

}